클로드 코드 완벽 가이드 — 27장 Claude Code Hooks 딥다이브 학습 노트
출처: 클로드 코드 완벽 가이드 (코드팩토리 최지호) | 참고: https://github.com/codefactory-co
27장에서 다루는 내용
- Claude Code Hooks 개념 — 특정 시점에 원하는 코드를 끼워 넣는 확장 기능
- 훅 기본 설정 — JSON 파일로 등록하는 방법, 설정 파일 위치(사용자/프로젝트/로컬)
- 훅 JSON 구조 — matcher, hooks, type, command, timeout 필드 이해
- 7가지 훅 이벤트 — PreToolUse, PostToolUse, Notification, UserPromptSubmit, Stop, SubagentStop, PreCompact
- 훅 입력 형태(stdin) — 공통 구조와 이벤트별 JSON 스키마
전체 흐름도
[사용자 프롬프트 입력]
|
v
+-------------------+ +-----------------------+
| UserPromptSubmit |---->| 훅 실행: 컨텍스트 추가 |
| (프롬프트 제출 전)| | 유효성 검사, 차단 등 |
+-------------------+ +-----------------------+
|
v
[클로드 코드가 도구 호출 결정]
|
v
+-------------------+ +-----------------------+
| PreToolUse |---->| 훅 실행: matcher로 |
| (도구 사용 전) | | 특정 도구만 필터링 |
+-------------------+ +-----------------------+
|
v
[도구 실행 (Bash, Write, Edit 등)]
|
v
+-------------------+ +-----------------------+
| PostToolUse |---->| 훅 실행: 도구 결과에 |
| (도구 사용 후) | | 따른 후처리 |
+-------------------+ +-----------------------+
|
v
[알림 발생 시]
|
v
+-------------------+ +-----------------------+
| Notification |---->| 훅 실행: 사용자 승인 |
| (알림 보낼 때) | | 대기, 60초 유휴 시 |
+-------------------+ +-----------------------+
|
v
[응답 완료 시]
|
v
+-------------------+ +-------------------+
| Stop |---->| 메인 에이전트 완료 |
| SubagentStop |---->| 서브에이전트 완료 |
+-------------------+ +-------------------+
|
v
[컨텍스트 압축 시]
|
v
+-------------------+ +-----------------------+
| PreCompact |---->| 훅 실행: 압축 전 처리 |
| (압축 실행 전) | | manual / auto 구분 |
+-------------------+ +-----------------------+
선수 지식 체크리스트
- [ ] 클로드 코드 기본 사용법 (터미널 명령어, 도구 개념)
- [ ] JSON 파일 구조 이해 (중첩 객체, 배열)
- [ ] bash 셸 명령어 기초 (스크립트 실행, 환경 변수)
- [ ] 정규식(Regex) 기본 개념
- [ ] stdin(표준 입력) 개념
핵심 키워드
| 키워드 | 의미 |
|---|---|
| Hook(훅) | 특정 시점에 원하는 코드를 끼워 넣을 수 있는 확장 기능. 프로그래밍에서 "갈고리"처럼 실행 흐름에 걸어두는 것 |
| matcher | 도구 이름과 일치하는 패턴. PreToolUse, PostToolUse에서 특정 도구에만 훅을 실행하도록 필터링 |
| PreToolUse | 클로드가 도구 매개변수를 생성하고 도구를 실행하기 전에 실행되는 훅 |
| PostToolUse | 도구가 성공적으로 완료된 직후에 실행되는 훅 |
| Notification | 클로드 코드가 알림을 보낼 때 실행. 사용자 승인 대기 또는 60초 유휴 시 |
| UserPromptSubmit | 사용자가 프롬프트를 제출할 때, 클로드가 처리하기 전에 실행 |
| Stop / SubagentStop | 메인 에이전트 / 서브에이전트가 응답을 마쳤을 때 실행 |
| PreCompact | 클로드가 컨텍스트 압축을 실행하기 전에 실행. manual(수동)과 auto(자동) 구분 |
| $CLAUDE_PROJECT_DIR | 훅 command에서 사용 가능한 환경 변수. 현재 프로젝트 디렉터리 경로 |
27-1 Claude Code Hooks 개념
한 줄 요약
클로드 코드 훅은 도구 사용 전후, 프롬프트 제출, 알림, 응답 완료, 압축 등 7가지 시점에 원하는 코드를 자동으로 실행할 수 있는 확장 기능이다.
쉬운 설명 (비유)
훅(Hook) = 요리 과정에 끼워 넣는 "중간 점검"
요리사(클로드 코드)가 요리를 한다고 하면:
- 재료 손질 전 → "재료 상태 점검!" (PreToolUse)
- 재료 손질 후 → "잘 손질됐나 확인!" (PostToolUse)
- 손님에게 알림 → "주문 확인!" (Notification)
- 주문서 받을 때 → "주문 내용 검증!" (UserPromptSubmit)
- 요리 완성 → "최종 맛 점검!" (Stop)
- 보조 요리사 완성 → "보조 결과 확인!" (SubagentStop)
- 냉장고 정리 전 → "뭘 버릴지 체크!" (PreCompact)
→ 각 단계마다 내가 원하는 검사/처리를 끼워 넣을 수 있다!
실무 예제
❌ 훅 없이 사용할 때:
클로드 코드가 파일을 수정할 때마다
수동으로 린트(lint) 검사를 실행해야 함
→ 까먹으면 코드 품질 저하!
✅ PostToolUse 훅을 설정할 때:
"Edit" 도구로 파일이 수정되면
자동으로 린트 검사 스크립트 실행!
→ 매번 자동으로 코드 품질 관리!
핵심 체크포인트
- [ ] 클로드 코드 훅이 "특정 시점에 코드를 끼워 넣는 기능"임을 설명할 수 있다
- [ ] 7가지 훅 이벤트의 이름을 모두 나열할 수 있다
- [ ] 훅을 사용하면 확장성과 맞춤화가 향상되는 이유를 이해한다
27-2 클로드 코드 훅 기본 설정
한 줄 요약
훅은 JSON 파일로 등록하며, 사용자 설정(~/.claude/settings.json), 프로젝트 설정(.claude/settings.json), 로컬 프로젝트 설정(.claude/settings.local.json) 세 곳에서 관리할 수 있다.
쉬운 설명 (비유)
훅 설정 파일 위치 = 규칙을 적용하는 범위
~/.claude/settings.json = 학교 전체 규칙 (모든 프로젝트에 적용)
.claude/settings.json = 우리 반 규칙 (이 프로젝트에만 적용)
.claude/settings.local.json = 나만의 규칙 (커밋 안 됨, 나만 사용)
→ 좁은 범위일수록 개인적인 설정!
→ .local.json은 Git에 올라가지 않아 비밀 설정에 적합!
실무 예제: JSON 구조
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo '쉘 명령 실행 전입니다!'"
}
]
}
]
}
}
각 필드의 역할:
┌─────────────────────────────────────────────────┐
│ hooks → 훅 설정의 최상위 키 │
│ └ "PreToolUse" → 이벤트 이름 (7가지 중 선택) │
│ └ matcher → 어떤 도구에 반응할지 (패턴) │
│ └ hooks[] → 실행할 명령 배열 │
│ └ type → "command" (현재 유일한 타입) │
│ └ command→ 실행할 bash 명령어 │
│ └ timeout→ (선택) 타임아웃 시간(초) │
└─────────────────────────────────────────────────┘
핵심 체크포인트
- [ ] 3가지 설정 파일 위치와 각각의 적용 범위를 구분할 수 있다
- [ ]
.local.json이 커밋되지 않는다는 특징을 이해한다 - [ ] JSON 구조에서 hooks → 이벤트명 → matcher → hooks[] → command 계층을 이해한다
27-3 matcher의 이해
한 줄 요약
matcher는 PreToolUse와 PostToolUse에서만 사용하며, 도구 이름과 일치하는 패턴을 지정하여 특정 도구에만 훅을 실행하도록 필터링한다.
쉬운 설명 (비유)
matcher = 택배 분류기
모든 택배(도구 호출)가 컨베이어 벨트에 올라오면
분류기(matcher)가 라벨을 확인:
"Bash" 라벨 → Bash 전용 훅 실행!
"Edit|MultiEdit|Write" → 파일 수정 관련 훅 실행!
그 외 → 통과 (훅 실행 안 함)
정규식 지원 → 여러 도구를 한 번에 매칭 가능!
실무 예제
matcher 패턴 예시:
1) "Bash" → Bash 도구만 정확히 매칭
2) "Edit|MultiEdit|Write" → 파일 수정 관련 도구 3개 모두 매칭 (정규식)
3) "Read" → 파일 읽기 도구만 매칭
4) "WebFetch|WebSearch" → 웹 관련 도구만 매칭
❌ 잘못된 이해:
"matcher는 모든 훅 이벤트에서 사용해야 한다"
✅ 올바른 이해:
"matcher는 PreToolUse와 PostToolUse에서만 사용한다.
UserPromptSubmit, Notification, Stop, SubagentStop,
PreCompact는 matcher 필드를 생략할 수 있다"
주요 도구(matcher에 사용 가능한 값)
| 도구 이름 | 설명 |
|---|---|
| Task | 에이전트 작업 |
| Bash | 셸 명령 |
| Glob | 파일 패턴 일치 |
| Grep | 내용 검색 |
| Read | 파일 읽기 |
| Edit, MultiEdit | 단일/여러 파일 수정 |
| Write | 파일 쓰기(생성) |
| WebFetch, WebSearch | 웹 작업 |
핵심 체크포인트
- [ ] matcher가 PreToolUse와 PostToolUse에서만 사용됨을 안다
- [ ] 단순 문자열과 정규식 두 가지 매칭 방식을 구분할 수 있다
- [ ] matcher가 대소문자를 구분함을 이해한다
27-4 7가지 훅 이벤트 정리
한 줄 요약
클로드 코드는 PreToolUse, PostToolUse, Notification, UserPromptSubmit, Stop, SubagentStop, PreCompact 총 7가지 훅 이벤트를 제공하며, 각각 고유한 실행 조건과 matcher 사용 여부가 다르다.
쉬운 설명 (비유)
7가지 훅 = 축구 경기의 7가지 체크포인트
PreToolUse = 선수가 공을 차기 직전 → "자세 점검!"
PostToolUse = 선수가 공을 찬 직후 → "결과 확인!"
Notification = 심판이 호루라기 불 때 → "상황 전달!"
UserPromptSubmit= 감독이 전술 지시할 때 → "전술 검증!"
Stop = 주심이 경기 종료할 때 → "최종 정리!"
SubagentStop = 부심이 판정 마칠 때 → "부심 결과 확인!"
PreCompact = 하프타임 정리할 때 → "정리 전 점검!"
이벤트별 상세 비교
| Hook 이름 | 설명 | matcher 사용 | 핵심 용도 |
|---|---|---|---|
| PreToolUse | 도구 매개변수 생성 → 실행 전 | O | 도구 실행 전 검증/차단 |
| PostToolUse | 도구 성공 완료 직후 | O | 실행 결과 후처리(린트 등) |
| Notification | 알림 보낼 때 (승인 대기/60초 유휴) | X | 알림 커스터마이징 |
| UserPromptSubmit | 프롬프트 제출 → 클로드 처리 전 | X | 컨텍스트 추가, 유효성 검사, 차단 |
| Stop | 메인 에이전트 응답 완료 (인터럽트 제외) | X | 응답 후 자동 처리 |
| SubagentStop | 서브에이전트 응답 완료 | X | 서브 작업 후처리 |
| PreCompact | 컨텍스트 압축 실행 전 | X (별도 matcher) | 압축 전 데이터 보존/로깅 |
실무 예제
실전 활용 시나리오별 추천 훅:
시나리오 1: "파일 수정 시 자동 포맷팅"
→ PostToolUse + matcher: "Edit|MultiEdit|Write"
→ command: "prettier --write $FILE_PATH"
시나리오 2: "프롬프트에 프로젝트 규칙 자동 주입"
→ UserPromptSubmit (matcher 불필요)
→ command: "cat $CLAUDE_PROJECT_DIR/.rules"
시나리오 3: "위험한 명령어 실행 전 경고"
→ PreToolUse + matcher: "Bash"
→ command: "echo '쉘 명령 실행 전 주의!'"
시나리오 4: "응답 완료 후 슬랙 알림"
→ Stop (matcher 불필요)
→ command: "curl -X POST slack-webhook-url"
PreCompact의 특수한 matcher
PreCompact는 도구 matcher 대신 trigger 값으로 구분:
- "manual" → 사용자가 /compact 명령어로 수동 압축할 때
- "auto" → 전체 컨텍스트 창이 가득 차서 자동 압축할 때
→ custom_instructions 필드로 사용자 지시 전달 가능 (수동 시)
→ 자동 압축 시에는 custom_instructions가 비어 있음
핵심 체크포인트
- [ ] 7가지 훅 이벤트를 모두 나열하고 각각의 실행 시점을 설명할 수 있다
- [ ] matcher를 사용하는 이벤트(PreToolUse, PostToolUse)와 사용하지 않는 이벤트를 구분한다
- [ ] PreCompact의 trigger(manual/auto) 구분을 이해한다
- [ ] Stop은 사용자 인터럽트로 중단된 경우에는 실행되지 않음을 안다
27-5 훅 입력 형태 (stdin JSON)
한 줄 요약
훅이 실행되면 stdin을 통해 세션 ID, 대화 경로, 작업 디렉터리 등의 공통 필드와 이벤트별 고유 필드가 JSON으로 전달된다.
쉬운 설명 (비유)
stdin JSON = 훅에게 전달되는 "작업 지시서"
모든 지시서에 공통으로 들어가는 정보:
┌─────────────────────────────────────┐
│ session_id → 이번 대화 번호 │
│ transcript_path → 대화 기록 위치 │
│ cwd → 현재 작업 폴더 │
│ hook_event_name → 어떤 이벤트인지 │
└─────────────────────────────────────┘
+ 이벤트마다 추가되는 고유 정보가 다름!
(도구 이름, 입력값, 결과값, 프롬프트 내용 등)
이벤트별 고유 필드 정리
PreToolUse 고유 필드:
├── tool_name → 호출될 도구 이름 (예: "Write", "Bash")
└── tool_input → 도구에 전달될 매개변수
├── file_path → (Write 도구) 작성될 파일 경로
└── content → (Write 도구) 작성될 내용
PostToolUse 고유 필드:
├── tool_name → 실행된 도구 이름
├── tool_input → 도구에 전달되었던 매개변수
└── tool_response → 도구 실행 결과
├── filePath → (Write) 작성된 파일 경로
└── success → (Write) 성공 여부 (boolean)
Notification 고유 필드:
└── message → 알림 메시지 내용
UserPromptSubmit 고유 필드:
└── prompt → 사용자가 입력한 프롬프트 내용
Stop / SubagentStop 고유 필드:
└── stop_hook_active → Stop 훅이 계속 진행 중인지 여부
PreCompact 고유 필드:
├── trigger → "manual" 또는 "auto"
└── custom_instructions → 수동 압축 시 사용자 지침 (자동 시 비어 있음)
실무 예제
❌ 잘못된 이해:
"모든 훅 이벤트가 동일한 JSON 구조를 받는다"
✅ 올바른 이해:
"공통 필드(session_id, cwd 등)는 동일하지만,
이벤트별 고유 필드가 다르다.
예: PreToolUse는 tool_name이 있고,
UserPromptSubmit은 prompt가 있다"
실전 스크립트 예시 (PostToolUse에서 결과 로깅):
─────────────────────────────────────
#!/bin/bash
# stdin에서 JSON을 읽어서 처리
INPUT=$(cat)
TOOL=$(echo $INPUT | jq -r '.tool_name')
SUCCESS=$(echo $INPUT | jq -r '.tool_response.success')
echo "[$TOOL] 실행 결과: $SUCCESS" >> hook_log.txt
─────────────────────────────────────
핵심 체크포인트
- [ ] 공통 필드 4가지(session_id, transcript_path, cwd, hook_event_name)를 알고 있다
- [ ] PreToolUse와 PostToolUse의 JSON 구조 차이를 설명할 수 있다
- [ ] tool_input과 tool_response의 스키마가 도구마다 다름을 이해한다
- [ ] stdin으로 JSON을 받아서 스크립트에서 처리하는 방법을 이해한다
연습문제
문제 1: 개념 이해 (기본)
클로드 코드 훅(Hook)이란 무엇인지 설명하고, 훅을 사용하면 얻을 수 있는 두 가지 이점을 서술하세요.
정답 보기
- **클로드 코드 훅**: 특정 시점에 원하는 코드를 끼워 넣을 수 있는 확장 기능이다. 도구 사용 전(PreToolUse), 도구 사용 후(PostToolUse), 알림(Notification), 프롬프트 제출(UserPromptSubmit), 응답 완료(Stop/SubagentStop), 압축 전(PreCompact) 등 7가지 시점에 bash 명령어를 자동 실행할 수 있다. - **이점 1 — 확장성**: 클로드 코드의 기본 동작에 사용자만의 커스텀 로직을 추가할 수 있어 다양한 상황에 유연하게 대응할 수 있다. - **이점 2 — 맞춤화**: 프로젝트 특성에 맞는 자동화(린트, 테스트, 알림 등)를 설정하여 작업 흐름을 세밀하게 제어할 수 있다.문제 2: 설정 구조 (중급)
클로드 코드 훅 설정 파일 3가지의 경로와 각각의 적용 범위를 설명하세요. 또한, 팀 공통 훅과 개인 전용 훅을 분리하려면 어떤 파일을 사용해야 하는지 설명하세요.
정답 보기
**3가지 설정 파일:** 1. `~/.claude/settings.json` — **사용자 설정**. 해당 사용자의 모든 프로젝트에 적용된다. 2. `.claude/settings.json` — **프로젝트 설정**. 해당 프로젝트에만 적용되며, Git으로 커밋하여 팀원과 공유할 수 있다. 3. `.claude/settings.local.json` — **로컬 프로젝트 설정**. 해당 프로젝트에만 적용되지만, 커밋되지 않아(Git 제외) 개인만 사용한다. **팀 공통 vs 개인 전용 분리:** - 팀 공통 훅 → `.claude/settings.json`에 설정 (커밋하여 팀 공유) - 개인 전용 훅 → `.claude/settings.local.json`에 설정 (커밋 안 됨)문제 3: 실전 시나리오 (심화)
다음 요구사항을 만족하는 훅 설정 JSON을 작성하세요: (1) 클로드 코드가 Edit 또는 Write 도구로 파일을 수정/생성한 직후에 자동으로
npm run lint명령어를 실행한다. (2) 타임아웃은 30초로 설정한다.
정답 보기
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npm run lint",
"timeout": 30
}
]
}
]
}
}
**해설:**
- `PostToolUse` — 도구가 성공적으로 완료된 직후 실행
- `matcher: "Edit|Write"` — Edit 또는 Write 도구에만 반응 (정규식 OR 패턴)
- `type: "command"` — 현재 유일하게 지원되는 타입
- `command: "npm run lint"` — 실행할 bash 명령어
- `timeout: 30` — 30초 내에 완료되지 않으면 취소
문제 4: 종합 분석 (심화)
PreToolUse와 PostToolUse 훅이 stdin으로 받는 JSON 구조의 공통점과 차이점을 설명하세요. PostToolUse에만 있는 필드는 무엇이며, 그 이유는?
정답 보기
**공통점:** - 공통 필드: session_id, transcript_path, cwd (모든 훅에 동일) - 둘 다 tool_name(도구 이름)과 tool_input(도구 입력 매개변수) 필드를 갖는다 - 둘 다 matcher를 사용하여 특정 도구에만 반응할 수 있다 **차이점:** - PreToolUse의 hook_event_name은 `"PreToolUse"`이고, PostToolUse는 `"PostToolUse"`이다 - **PostToolUse에만 있는 필드**: `tool_response` (도구 실행 결과) - 예: Write 도구의 경우 `filePath`(작성된 파일 경로)와 `success`(성공 여부) 포함 **이유:** - PreToolUse는 도구 실행 **전**이므로 아직 결과가 없다. 따라서 tool_response가 존재하지 않는다. - PostToolUse는 도구 실행 **후**이므로 실행 결과(tool_response)를 포함하여 후처리에 활용할 수 있다.부록 A: 용어 사전
| 용어 | 정의 |
|---|---|
| Hook(훅) | 프로그램 실행 흐름의 특정 시점에 사용자 정의 코드를 끼워 넣는 확장 메커니즘 |
| matcher | PreToolUse/PostToolUse에서 어떤 도구에 훅을 적용할지 결정하는 패턴 문자열 (정규식 지원) |
| PreToolUse | 클로드가 도구를 호출하기 직전에 실행되는 훅 이벤트 |
| PostToolUse | 도구가 성공적으로 완료된 직후 실행되는 훅 이벤트 |
| Notification | 클로드 코드가 알림을 보낼 때 실행되는 훅 이벤트. 사용자 승인 대기 또는 60초 유휴 시 발동 |
| UserPromptSubmit | 사용자의 프롬프트가 제출될 때 클로드가 처리하기 전에 실행되는 훅 이벤트 |
| Stop | 메인 클로드 코드 에이전트가 응답을 완료했을 때 실행. 사용자 인터럽트 시 실행 안 됨 |
| SubagentStop | 클로드 코드의 서브에이전트가 응답을 마쳤을 때 실행되는 훅 이벤트 |
| PreCompact | 클로드가 컨텍스트 압축을 실행하기 전에 실행. trigger로 manual/auto 구분 |
| stdin | 표준 입력. 훅 실행 시 이벤트 정보가 JSON 형태로 전달되는 채널 |
| $CLAUDE_PROJECT_DIR | 훅 command에서 사용 가능한 환경 변수. 현재 프로젝트의 루트 디렉터리 경로 |
| tool_input | 도구에 전달될/전달된 입력 매개변수. 도구마다 스키마가 다르다 |
| tool_response | PostToolUse에서만 제공되는 도구 실행 결과 객체 |
부록 B: 비교표
matcher 사용 여부별 훅 이벤트 분류
| 분류 | 훅 이벤트 | matcher 필요 여부 |
|---|---|---|
| 도구 관련 | PreToolUse | 필요 (도구 필터링) |
| 도구 관련 | PostToolUse | 필요 (도구 필터링) |
| 알림 관련 | Notification | 생략 가능 |
| 프롬프트 관련 | UserPromptSubmit | 생략 가능 |
| 완료 관련 | Stop | 생략 가능 |
| 완료 관련 | SubagentStop | 생략 가능 |
| 압축 관련 | PreCompact | 별도 matcher (trigger) |
설정 파일 3종 비교
| 비교 항목 | ~/.claude/settings.json | .claude/settings.json | .claude/settings.local.json |
|---|---|---|---|
| 적용 범위 | 사용자 전체 (모든 프로젝트) | 해당 프로젝트 | 해당 프로젝트 |
| Git 커밋 | 해당 없음 (홈 디렉터리) | 커밋 가능 (팀 공유) | 커밋 불가 (개인용) |
| 추천 용도 | 개인 글로벌 설정 | 팀 공통 규칙 | 개인 로컬 실험 |
PreToolUse vs PostToolUse 입력 JSON 비교
| 필드 | PreToolUse | PostToolUse |
|---|---|---|
| session_id | O | O |
| transcript_path | O | O |
| cwd | O | O |
| hook_event_name | "PreToolUse" | "PostToolUse" |
| tool_name | O | O |
| tool_input | O | O |
| tool_response | X (도구 실행 전) | O (도구 실행 결과) |
hooks 배열 내 필드
| 필드 | 필수 여부 | 설명 |
|---|---|---|
| type | 필수 | 현재 "command"만 지원 |
| command | 필수 | 실행할 bash 명령어. $CLAUDE_PROJECT_DIR 환경 변수 사용 가능 |
| timeout | 선택 | 명령이 취소되기 전까지의 제한 시간(초) |
부록 C: 참고 자료
| 자료 | 링크/설명 |
|---|---|
| Claude Code Hooks 공식 문서 | https://docs.anthropic.com/en/docs/claude-code/hooks |
| 클로드 코드 공식 문서 | https://docs.anthropic.com/en/docs/claude-code |
| 코드팩토리 GitHub | https://github.com/codefactory-co |
| JSON 기초 가이드 | https://developer.mozilla.org/ko/docs/Learn/JavaScript/Objects/JSON |
| 정규식(Regex) 가이드 | https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_expressions |
클릭하거나 Space를 눌러 뒤집기